<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2020/12/10
 * Time: 17:02
 */
namespace app\common\widget\send;
use app\common\config\send_config;
use app\common\helper\appmsg_helper;
use app\common\helper\appmsg_send_helper;
use app\common\helper\send_helper;
use app\common\helper\setting_helper;
use app\common\helper\user_helper;
use app\common\helper\weixin_helper;
use app\common\model\Appmsg;
use app\common\model\AppmsgSend;
use app\common\model\SendQueue;
use app\common\model\SendTask;
use app\common\model\SendThread;
use app\common\model\Setting;
use app\common\widget\weixin\mass_widget;
use app\common\widget\weixin\material_widget;
use app\common\widget\weixin\weixin_widget;

/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2020/12/8
 * Time: 18:00
 */
class send_new_widget
{
    private $per_page = 10;

    /**
     * 群发素材
     */
    public function do_send_queue()
    {
        //echo '11';exit;
        $setting_info = _uri('setting', array('field'=>'send_queue_list'));
        if (!$setting_info || $setting_info['value'] == 1) {
            return false;
        }

        // 加锁
        Setting::update(['value' => 1], ['id' => $setting_info['id']]);

        // 拼装条件，获取等待同步的图文
        $need_send_filter = array(
            //'progress >='  => 1,
            //'progress <'  => 10,
            'progress'     => 1,
            'status'       => 1
        );
        // 限制每次只取几条
        $limit_num = 5;
        $need_send_list = getList('send_queue',$need_send_filter, ['id', 'asc'], 0, $limit_num);
        if (!$need_send_list) {
            Setting::update(['value' => 0], ['id' => $setting_info['id']]);
            echo 'no more '.__FILE__.__LINE__;
            return;
        }

        // 循环同步图文素材
        foreach ($need_send_list as $k=>$v) {
            // 同步素材到微信公众平台
            $res = $this->do_send_single_queue($v);
        }

        // 解锁
        Setting::update(['value' => 0], ['id' => $setting_info['id']]);

        echo 'success';
    }

    /**
     * 执行群发队列的计划任务
     * @return string
     */
    public function do_send_single_queue($need_send_info)
    {
        /*
        $need_send_filter = array(
                        'progress >='  => 1,
                        'progress <='  => 10,
                        'status'       => 1
        );
        $need_send_info = _model('send_queue')->read($need_send_filter, ' ORDER BY `id` ASC ');
        */
        if (!$need_send_info) {
            echo 'no more'.__LINE__;
            return false;
        }

        if ($need_send_info['progress'] == 2) {
            echo 'record：'.$need_send_info['id'].' is in sending ';
            return false;
        }

        if ($need_send_info['progress'] == 10) {
            echo 'record：'.$need_send_info['id'].' has pushed, is in weixin sending ';
            return false;
        }

        // progress=2，表示正在处理中
        SendQueue::update(['progress' => 2], ['id' => $need_send_info['id']]);
        // 本次要发送的消息类型
        $send_msg_type = $need_send_info['type'] ;
        $tag_id = 0;
        // 要发送的media_id
        $media_id = '';
        // 要发送的文本
        $content = '';
        // 发送失败的原因
        $fail_reason = '';

        // 允许群发的类型
        $send_msg_type_arr = send_config::$send_msg_type;
        if (!array_key_exists($send_msg_type, $send_msg_type_arr)) {
            $fail_reason =  '群发类型不支持';
            SendQueue::update(['progress'=>15, 'reason'=>$fail_reason], ['id' => $need_send_info['id']]);
            return $fail_reason;
        }
        if (in_array($send_msg_type, array(40, 50))) {
            $appmsg_list = appmsg_send_helper::get_appmsg_list((int)$need_send_info['content']);
            if (!$appmsg_list) {
                $fail_reason = '该图文信息不存在';
                SendQueue::update(['progress'=>15, 'reason'=>$fail_reason], ['id' => $need_send_info['id']]);
                return $fail_reason;
            }
            if (!$appmsg_list[0]['media_id']) {
                $fail_reason = '该图文尚未同步到公众平台，请先同步';
                SendQueue::update(['progress'=>15, 'reason'=>$fail_reason], ['id' => $need_send_info['id']]);
                return $fail_reason;
            }

            $media_id = $appmsg_list[0]['media_id'];

        } else {
            $content = $need_send_info['content'];
        }

        $succ_update_info = array(
            'progress'  => 10   // 10表示调用接口推送成功
        );

        //dump($need_send_info);
        $res = '关闭发送';
        // 发送给所有人的
        if ($need_send_info['to_store_id'] == -1) {
            $mass_params = array(
                'is_to_all'     => 1,
                'media_type'    => $send_msg_type_arr[$send_msg_type],
                'media_id'      => $media_id,
                'content'       => $content
            );
            $res = (new mass_widget())->mass_sendall($mass_params);

            // 如
        }  else if ( 1 == 1 ) {
            $tag_id = 0;
            if (!$need_send_info['to_store_id']) {
                //$tag_id = store_helper::get_quan_guo_group_id();
                $tag_id = 0;
            } else {
                $store_info = get_res_info('store', $need_send_info['to_store_id']);
                if ($store_info && $store_info['tag_id']) {
                    $tag_id = $store_info['tag_id'];
                }
            }

            if ($tag_id) {
                $mass_params = array(
                    'tag_id'        => $tag_id,
                    'media_type'    => $send_msg_type_arr[$send_msg_type],
                    'media_id'      => $media_id,
                    'content'       => $content
                );

                $res =(new mass_widget())->mass_sendall($mass_params);

            } else {
                $res = '店铺不存在对应的标签';
                $fail_reason =  '店铺不存在对应的标签';
                SendQueue::update(['progress'=>15, 'reason'=>$fail_reason], ['id' => $need_send_info['id']]);
                return $fail_reason;
            }

            // 如
        } else if ( 1 == 2) {
            $store_target = $need_send_info['store_target'];
            // 重新拆分
            if (strpos($store_target, ',') !== false) {
                $store_target = explode(',', trim($store_target, ','));
            }

            // 该店铺下成员
            $store_user_num = user_helper::get_user_num_by_filter(array('store_id'=>$store_target, 'is_subscribe'=>1));
            if ($store_user_num < 1) {
                $fail_reason =  '该店铺下无成员';
                SendQueue::update(['progress'=>15, 'reason'=>$fail_reason], ['id' => $need_send_info['id']]);

                return $fail_reason;
            }

            //@FIXME 生成send_thread队列
            $flag = $this->create_send_thread($need_send_info, $store_target);
            //an_dump($flag.' thread create '.__LINE__);
            //exit;
            //@FIXME 循环发送thread队列
            $res = $this->do_send_thread($need_send_info['id'], $send_msg_type, $media_id, $content);

            // 发给给某一店铺下的所有人的
        } else if (1 == 3) {
            $store_info = get_res_info('store', $need_send_info['to_store_id']);
            // 先判断该店铺是否有标签，如果有标签的按标签发送，加1==2让该分支失效
            if ($store_info && $store_info['tag_id'] && 1 == 2) {
                $tag_id = $store_info['tag_id'];

                // 如果没标签的，则把相人员转移到该标签下去，然后再按该标签来发送
            } else {
                $store_target = $need_send_info['store_target'];
                // 重新拆分
                if (strpos($store_target, ',') !== false) {
                    $store_target = explode(',', trim($store_target, ','));
                }

                // 该店铺下成员
                $store_user_num = user_helper::get_user_num_by_filter(array('store_id'=>$store_target, 'is_subscribe'=>1));
                if ($store_user_num < 1) {
                    $fail_reason =  '该店铺下无成员';
                    SendQueue::update(['progress'=>15, 'reason'=>$fail_reason], ['id' => $need_send_info['id']]);
                    return $fail_reason;
                }

                // @todo 这个临时$tmp_tag_id的获取
//                if (ONDEV) {
//                    $tmp_tag_id = 103;
//                } else {
                    //$tmp_tag_id = 199;
                    $tmp_tag_id = 111;
//                }

                $tag_id = $tmp_tag_id;

                // 先清空上次在临时标签里存的用户
                $clear_send_tag_res = $this->clear_send_tmp_tag($store_target, $need_send_info['id'], $tag_id);
                //an_dump($clear_send_tag_res);

                // ======================================
                // 保存log看走哪了
                $api_log_info = array(
                    'file'      => substr(__FILE__, strrpos(__FILE__, '/')+1),
                    'action'    => __FUNCTION__,
                    'request'   => 'clear tag user, _queue:'.$need_send_info['id'].'_line:'.__LINE__
                );
                weixin_helper::add_api_log($api_log_info);
                // ======================================


                // 再转移新的用户到临时标签，注意此外传递的store_target，可以是数id，也可能是数组
                $add_send_tag_res = $this->send_by_tmp_tag($store_target, $need_send_info['id'], $tag_id);
                //an_dump($add_send_tag_res);

                // ======================================
                // 保存log看走哪了
                $api_log_info = array(
                    'file'      => substr(__FILE__, strrpos(__FILE__, '/')+1),
                    'action'    => __FUNCTION__,
                    'request'   => 'add tag user, _queue:'.$need_send_info['id'].'_line:'.__LINE__
                );
                weixin_helper::add_api_log($api_log_info);
                // ======================================

            }

            // 处理好标签与用户关系后，开始推送
            $mass_params = array(
                'is_to_all'     => 0,
                'tag_id'        => $tag_id,
                'media_type'    => $send_msg_type_arr[$send_msg_type],
                'media_id'      => $media_id,
                'content'       => $content
            );
            $res = (new mass_widget())->mass_sendall($mass_params);

            $succ_update_info['wx_tag_id'] = $tag_id;
        }

        //dump($res);
        //exit;
        // 推送失败
        if ($res != 'ok') {
            if (!is_array($res)) {
                $fail_reason =  $res;
                SendQueue::update(['progress'=>15, 'reason'=>$fail_reason], ['id' => $need_send_info['id']]);
                return $fail_reason;
            }

            // 推送失败
            if (!isset($res['res']['msg_id'])) {
                $fail_reason =  json_encode($res);
                SendQueue::update(['progress'=>15, 'reason'=>$fail_reason], ['id' => $need_send_info['id']]);
                return $fail_reason;
            }

            // 推送接口返回的微信方产生的推送任务id
            $succ_update_info['wx_msg_id'] = $res['res']['msg_id'];
        }

        // 推送成功后，做更新
        SendQueue::update($succ_update_info, ['id' => $need_send_info['id']]);
        // 更新完后，把真实的appmsg更新为已发送，做此操作的原因：群发时取店铺图文要求取的是审核销通过且未发送的
        if (in_array($need_send_info['type'], array(40, 50))) {
            $appmsg_send_list = appmsg_send_helper::get_appmsg_list((int)$need_send_info['content']);
            foreach ($appmsg_send_list as $k=>$v) {
                update_res_field('appmsg', (int)$v['appmsg_id'], array('send'=>1, 'send_time'=>date('Y-m-d H:i:s')));
            }
        }

        echo 'success '.__LINE__;
    }

    /**
     * 生成queue的send_thread
     * @param array $need_send_info
     * @param array $store_target
     */
    public function create_send_thread($need_send_info, $store_target)
    {
        if (!$need_send_info) {
            return '发送队列不存在';
        }

        if (!$store_target) {
            return '发送目标不能为空';
        }

        // 如果已经创建过thread，就不用再次创建了
        $old_thread_info = _uri('send_thread', ['send_queue_id'=>$need_send_info['id']]);
        if ($old_thread_info) {
            return 'ok';
        }

        // 拼装要添加的send_thread
        $new_thread_info = array(
            'send_task_id'  => $need_send_info['send_task_id'],
            'send_queue_id' => $need_send_info['id'],
            'progress'      => 1
        );

        $page = 1;
        $pre_page = 500;

        $order      =  ['id' , 'asc'];
        //$limit      = ' LIMIT '.($page-1)*$pre_page.','.$pre_page;
        $limit      = $pre_page;
        $filter     = array(
            ['store_id', '=', $store_target],
            ['is_subscribe', '=', 1]
        );

        // 待拼装的要发送的open_ids，上限为1W
        $thread_open_ids = array();
        $thread_id = 0;

        $user_ids = getFields('user', 'id', $filter, $order, $limit);
        while (!empty($user_ids)) {
            // 取本次的open_ids
            $open_ids = getFields('user', 'open_id', ['id', 'in', $user_ids], ['id' , 'desc']);
            // 没有了也要重新创建

            // 超过1W，就要重新创建了
            if (count($thread_open_ids) >= 10000) {
                $new_thread_info['open_id_str'] = join(',', $thread_open_ids);
                $thread = SendThread::create($new_thread_info);
                $thread_id = $thread->id;
                // 清空
                $thread_open_ids = array();
            }

            $thread_open_ids = array_merge($thread_open_ids, $open_ids);
            //an_dump($order, $limit, $open_ids);exit;

            // =========== end =========================

            usleep(500);

            if ($user_ids) {
                ++$page;
                $filter[] = ['id', '>', $user_ids[count($user_ids) - 1]];

                $user_ids = getFields('user', 'id', $filter, $order, $limit);
            }
        }

        // 如果还有$thread_open_ids，即不满足1W的
        if ($thread_open_ids) {
            $new_thread_info['open_id_str'] = join(',', $thread_open_ids);
            $thread = SendThread::create($new_thread_info);
            $thread_id = $thread->id;
            // 清空
            $thread_open_ids = array();
        }

        return 'ok';
    }

    /**
     * 发送queue的send_thread
     * @param array $need_send_info
     * @param array $store_target
     */
    public function do_send_thread($send_queue_id, $send_msg_type, $media_id, $content)
    {
        $res = '没有队列线程';

        $page = 1;
        $pre_page = 2;

        $order      = ['id', 'asc'];
        //$limit      = ' LIMIT '.($page-1)*$pre_page.','.$pre_page;
        $limit      = $pre_page;
        $filter = array(
            'send_queue_id' => $send_queue_id,
            'progress'      => 1
        );

        // 可发消息的类型
        $send_msg_type_arr = send_config::$send_msg_type;

        $thread_list = getList('send_thread', $filter, $order, 0, $limit);
        while (!empty($thread_list)) {
            // 循环发送send_thread
            foreach ($thread_list as $k=>$v) {
                // 发送thread
                $mass_params = array(
                    'media_type'    => $send_msg_type_arr[$send_msg_type],
                    'media_id'      => $media_id,
                    'content'       => $content
                );
                $openids_arr = explode(',', $v['open_id_str']);
                $res = (new mass_widget())->mass_send($openids_arr, $mass_params);

                if (!is_array($res)) {
                    $fail_reason =  $res;
                    return $fail_reason;
                }

                // 推送失败
                if (!isset($res['res']['msg_id'])) {
                    $fail_reason =  json_encode($res);
                    _model('send_thread')->update($v['id'], array('progress'=>15, 'reason'=>$fail_reason));
                    SendThread::update(['progress'=>15, 'reason'=>$fail_reason], ['id' => $v['id']]);

                    return $fail_reason;
                }

                $succ_update_info = array(
                    'progress'  => 10   // 10表示调用接口推送成功
                );
                // 推送接口返回的微信方产生的推送任务id
                $succ_update_info['wx_msg_id'] = $res['res']['msg_id'];

                // 推送成功后，做更新
                SendThread::update($succ_update_info, ['id' => $v['id']]);
            }
            // =========== end =========================

            usleep(500);

            if ($thread_list) {
                ++$page;
                $filter['id >'] = $thread_list[count($thread_list) - 1]['id'];

                $thread_list = _model('send_thread')->getList($filter, $order.$limit);
                $thread_list = getList('send_thread', $filter, $order, 0, $limit);
            }
        }

        return 'ok';
    }

    /**
     * 验证发送情况
     */
    public function check_send()
    {
        //echo '11';exit;
        $setting_info = _uri('setting', array('field'=>'send_queue_check'));
        if (!$setting_info || $setting_info['value'] == 1) {
            return false;
        }

        // 将当前任务计划改为已占用
        Setting::update(['value' => 1], ['id' => $setting_info['id']]);

        $page = 1;
        $pre_page = 50;

        $order      = ['id', 'asc'];
        //$limit      = ' LIMIT '.($page-1)*$pre_page.','.$pre_page;
        $limit      = $pre_page;
        $filter     = array(
            ['progress' ,'=', 10]
        );

        $send_list = getList('send_queue', $filter, $order, 0);
        while (!empty($send_list)) {
            foreach ($send_list as $k=>$v) {
                $res = (new mass_widget())->mass_send_check($v['wx_msg_id']);
                // 如果推送成功，更新推送信息的状态为20
                if (is_array($res) && $res['info'] == 'ok') {
                    SendQueue::update(['progress'=>20], ['id' => $v['id']]);
                }
            }

            usleep(500);

            if ($send_list) {
                ++$page;
                $filter[] = ['id', '>', $send_list[count($send_list) - 1]['id']];
                $send_list = getList('send_queue', $filter, $order, 0);
            }
        }

        // 将当前任务计划改为无人使用
        Setting::update(['value' => 0], ['id' => $setting_info['id']]);
        echo 'success';
    }

    /**
     * 发送前先清除上次在临时tag中关联的用户，即取消用户与临时标签的关联关系
     * @param int $store_id
     * @param int $send_queue_id
     * @param int $tag_id
     */
    public function clear_send_tmp_tag($store_id, $send_queue_id = 0, $tag_id = 0)
    {
        /*
         $setting_info = _uri('setting', array('field'=>'queue'));

         if (!$setting_info || $setting_info['value'] == 1) {
         return false;
         }

         // 将当前任务计划改为已占用
         _model('setting')->update($setting_info['id'], array('value'=>1));
         */

        $page = 1;
        $pre_page = 50;

        $order      = ['id', 'asc'];
        //$limit      = ' LIMIT '.($page-1)*$pre_page.','.$pre_page;
        $limit      = $pre_page;
        $filter     = array(
            ['tag_id','in', $tag_id],
            //'is_follow'     => 1
        );

        //dump('clear out while');

        $send_tag_list = getList('send_tag', $filter, $order, 0, $limit);
        while (!empty($send_tag_list)) {
            $open_ids = array();
            foreach ($send_tag_list as $k=>$v) {
                array_push($open_ids, $v['open_id']);
            }

            //dump('clear in while');

            // =========== start =========================
            // 批量取消该标签下的用户
            $tag_user_data = array(
                ['open_ids', 'in', $open_ids],
                ['tag_id'  , 'in', $tag_id]
            );

            //$res = _widget('weixin.tag')->del_user_tag($tag_user_data);

            //dump($res);exit;


            // 同时清除本次已转移的user
            foreach ($send_tag_list as $k=>$v) {
                $new_send_tag_info = array(
                    'tag_id'    => $tag_id,
                    'user_id'   => $v['user_id']
                );
                send_helper::del_send_tag($new_send_tag_info);
            }
            // =========== end =========================

            usleep(500);

            if ($send_tag_list) {
                ++$page;
                $filter['id >'] = $send_tag_list[count($send_tag_list) - 1]['id'];
                $filter[] = ['id', '>', $send_tag_list[count($send_tag_list) - 1]['id']];
                $send_tag_list = getList('send_tag', $filter, $order, 0, $limit);
            }
        }

        // 将当前任务计划改为无人使用
        //_model('setting')->update($setting_info['id'], array('value'=>0));

        return 'ok';
    }

    /**
     * 转移真正要发送的用户到临时标签下
     * @param int $store_id
     * @param int $send_queue_id
     * @param int $tag_id
     */
    public function send_by_tmp_tag($store_id, $send_queue_id = 0, $tag_id = 0)
    {
        /*
        $setting_info = _uri('setting', array('field'=>'queue'));

        if (!$setting_info || $setting_info['value'] == 1) {
            return false;
        }

        // 将当前任务计划改为已占用
        _model('setting')->update($setting_info['id'], array('value'=>1));
        */
        /*
        $page = 1;
        $pre_page = 50;

        $order      = 'ORDER BY `id` ASC ';
        //$limit      = ' LIMIT '.($page-1)*$pre_page.','.$pre_page;
        $limit      = ' LIMIT 0,'.$pre_page;
        $filter     = array(
            'store_id'      => $store_id,
            'is_subscribe'  => 1
        );

        $user_list = _model('user')->getList($filter, $order.$limit);
        while (!empty($user_list)) {
            $open_ids = array();
            foreach ($user_list as $k=>$v) {
                array_push($open_ids, $v['open_id']);
            }

            //an_dump($order, $limit, $open_ids);exit;
            // =========== start =========================
            // 批量给用户打标签
            $tag_user_data = array(
                'open_ids'  => $open_ids,
                'tag_id'    => $tag_id
            );
            $res = _widget('weixin.tag')->change_user_tag($tag_user_data);
            if ($res) {
                //@todo
            }
            //an_dump($tag_user_data, $res);exit;

            // 记录下本次转移的user
            foreach ($user_list as $k=>$v) {
                $new_send_tag_info = array(
                    'send_queue_id' => $send_queue_id,
                    'tag_id'        => $tag_id,
                    'user_id'       => $v['id'],
                    'open_id'       => $v['open_id'],
                    'wx_result'     => $user_list[0]['id'].'_'.$user_list[count($user_list)-1]['id'].' '.$res
                );
                send_helper::add_send_tag($new_send_tag_info);
            }
            // =========== end =========================

            usleep(500);

            if ($user_list) {
                ++$page;
                $filter['id >'] = $user_list[count($user_list) - 1]['id'];

                $user_list     = _model('user')->getList($filter, $order.$limit);
            }
        }

        // 将当前任务计划改为无人使用
        //_model('setting')->update($setting_info['id'], array('value'=>0));
        */
        return 'ok';
    }

    public function test_sync_tag()
    {
        /*
        $id = 43;
        $need_send_info = _model('send_queue')->read($id);
        if (!$need_send_info) {
            echo 'no more'.__LINE__;
            exit;
        }*/

        //$tag_id = 199;
        $tag_id = 111;


        $clear_send_tag_res = $this->clear_send_tmp_tag(0, 0, $tag_id);
        dump($clear_send_tag_res);exit;

        // 再转移新的用户到临时标签
        //$add_send_tag_res = $this->send_by_tmp_tag($need_send_info['to_store_id'], $need_send_info['id'], $tag_id);
        //an_dump($add_send_tag_res);
    }

}